package com.example.kingdee.KingdeeCreate.impl;

import cn.hutool.core.date.DateTime;
import com.example.kingdee.KingdeeCreate.CreateBill;
import com.example.kingdee.KingdeeCreate.dto.CreateInDto;
import com.example.kingdee.common.UUIDUtils;
import com.example.kingdee.exception.ProcedureException;
import com.example.kingdee.kingdeeBridge.common.RequestResult;
import com.example.kingdee.kingdeeBridge.dto.BillWriteInDto;
import com.example.kingdee.kingdeeBridge.dto.PushDto;
import com.example.kingdee.kingdeeBridge.kingdeeAbs.FolderKingdee;
import com.example.kingdee.kingdeeBridge.kingdeeImpl.impl.*;
import com.example.kingdee.mapper.TBxStMapper;
import com.example.kingdee.sqlTool.SqlTool;
import com.example.kingdee.sqlTool.common.DataObject;
import com.example.kingdee.sqlTool.common.QueryObject;
import com.example.kingdee.sqlTool.sqltoolEnum.FormIdEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 创建生产订单
 */
@Service
public class CreateProBillImpl implements CreateBill {

    @Autowired
    private SqlTool sqlTool;
    @Autowired
    private TBxStMapper tBxStMapper;
    @Autowired
    private PickMtlImpl pickMtl;
    @Autowired
    private ProInStockImpl proInStock;
    @Autowired
    private PpBomImpl ppBom;

    //前置操作
    @Override
    public void preposition(CreateInDto createInDto) {

    }

    @Override
    public RequestResult createSrcBill(CreateInDto createInDto) {
        //单据类型 (必填项) FBillType
        Map<String, Object> billType = new HashMap<>();
        billType.put("FNumber", "SCDD03_SYS");
        //生产组织：FPrdOrgId  (必填项)
        Map<String, Object> prdOrgId = new HashMap<>();
        prdOrgId.put("FNumber", createInDto.getReserved9());
        //订单明细  FSaleOrderEntry
        List<Map<String, Object>> orderInfoList = new ArrayList<>();
        List<Map<String, Object>> entryList = createInDto.getEntryList();
        String parentRowId = UUIDUtils.getId();
        for (Map<String, Object> item : entryList) {
            Map<String, Object> materialId = new HashMap<>(); //物料编码 必填 FMaterialId
            materialId.put("FNumber", item.get("itemNumber"));
            Map<String, Object> workShopID = new HashMap<>(); //生产车间 FWorkShopID
            workShopID.put("FNumber", createInDto.getReserved8());
            Map<String, Object> unitId = new HashMap<>(); //单位：FUnitId  (必填项)
            unitId.put("FNumber", item.get("unitNumber"));
            Map<String, Object> stockInOrgId = new HashMap<>(); //入库组织：FStockInOrgId  (必填项)
            stockInOrgId.put("FNumber", item.get("orgNumber"));
            Map<String, Object> bomId = new HashMap<>(); //BOM版本：FStockInOrgId  (必填项)
            bomId.put("FNumber", item.get("bomNumber"));

            Map<String,Object> saleOrderEntry = new LinkedHashMap<>();
            saleOrderEntry.put("FProductType", item.get("itemType"));//产品类型：FProductType  (必填项)
            saleOrderEntry.put("FMaterialId", materialId);//物料编码 必填
            saleOrderEntry.put("FWorkShopID", workShopID);//生产车间 FWorkShopID
            saleOrderEntry.put("FUnitId", unitId);//单位：FUnitId  (必填项)
            saleOrderEntry.put("FQty", item.get("qty"));//数量：FQty
            saleOrderEntry.put("F_QNSD_Text5", item.get("heatNumber"));//追溯炉号
            saleOrderEntry.put("FBaseUnitQty", item.get("qty"));//基本单位数量
            saleOrderEntry.put("FBaseYieldQty", item.get("qty"));//基本单位数量
            saleOrderEntry.put("FBaseStockInLimitH", item.get("qty"));//基本单位入库上限
            saleOrderEntry.put("FBaseStockInLimitL", item.get("qty"));//基本单位入库下限
            saleOrderEntry.put("FPlanStartDate", item.get("startTime"));//计划开工时间：FPlanStartDate  (必填项)
            saleOrderEntry.put("FPlanFinishDate", item.get("endTime"));//计划完工时间：FPlanFinishDate  (必填项)
            saleOrderEntry.put("FConveyDate", item.get("startTime"));//计划下达日期：FPlanFinishDate  (必填项)
            saleOrderEntry.put("FBomId", bomId);//BOM版本：FPlanFinishDate  (必填项)
            saleOrderEntry.put("FStockInOrgId", stockInOrgId);//入库组织：FStockInOrgId  (必填项)
            saleOrderEntry.put("FReqType", "1");//需求类型：FReqType  (必填项)
            saleOrderEntry.put("FCreateType", "1");//生成方式：FCreateType  (必填项)
            saleOrderEntry.put("FScheduleStatus", "1");//排产状态：FScheduleStatus  (必填项)
            saleOrderEntry.put("FFirstInspectStatus", "A");//首检状态：FFirstInspectStatus  (必填项)
            saleOrderEntry.put("FGroup", 1);//组别(必填项)
//            saleOrderEntry.put("FStatus", "4");//业务状态：FStatus  (必填项)
            if (item.get("itemType").toString().equals("1")){
                saleOrderEntry.put("FRowId", parentRowId);//行id： (必填项)
                saleOrderEntry.put("FISBACKFLUSH", true);//倒冲领料： (必填项)
                saleOrderEntry.put("FRowExpandType", 16);//行展开类型： (必填项)
            }else {
                saleOrderEntry.put("FRowId", UUIDUtils.getId());//行id： (必填项)
                saleOrderEntry.put("FParentRowId", parentRowId);//父行id： (必填项)
                saleOrderEntry.put("FISNEWLC", 1);//是否手工新增联副产品： (必填项)
                saleOrderEntry.put("FStartDate", item.get("startTime"));//开工日期
            }
            orderInfoList.add(saleOrderEntry);
        }
        //添加销售订单
        DataObject saleOrder = new DataObject(FormIdEnum.proMo);
        saleOrder.setIsEntryBatchFill(false);
        saleOrder.setIsAutoAdjustField(true);
        saleOrder.setAttribute("FBillType", billType);//单据类型 (必填项)
        saleOrder.setAttribute("FDate", SqlTool.getNowForString());//单据日期：FDate  (必填项)
        saleOrder.setAttribute("FPrdOrgId", prdOrgId);//生产组织：FPrdOrgId  (必填项)
        saleOrder.setAttribute("FOwnerTypeId", "BD_OwnerOrg");//货主类型：FOwnerTypeId  (必填项)
        saleOrder.setAttribute("FPPBOMType", "1");//用料清单展开：FPPBOMType  (必填项)
        saleOrder.setAttribute("FTreeEntity", orderInfoList);//订单明细

        try {
            Map<String, Object> result = sqlTool.editForDataObject(saleOrder);
            if (result.get("code").toString().equals("200")){
                return RequestResult.ofSuccess(result);
            }else {
                return RequestResult.ofError(result.get("msg").toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new ProcedureException("无法调用云星空接口");
        }
    }

    @Override
    public void auditTargetBill(String billNo) {
        //提交审核
        sqlTool.auditBill(billNo, FormIdEnum.proMo);
    }

    @Override
    public void postPosition(RequestResult moBill, CreateInDto createInDto) {
        //将生产订单行执行至开工
        try {
            //修改替代料比例
            ppBomChange(moBill, createInDto);
            sqlTool.excuteStartWork(moBill.getId(), FormIdEnum.proMo, "ToStart");
        }catch (Exception e){
            deleteTargetBill(moBill.getId());
            throw new ProcedureException("生产订单行执行至开工失败");
        }
        //下推生产领料
        String pickMtlId = moToMtrl(moBill, createInDto);
        if (createInDto.getReserved10().toString().equals("1")){
            //下推生产入库
            String moToMoInStock = moToMoInStock(moBill, createInDto, pickMtlId);
        }
    }

    public void postPositionTest(RequestResult moBill, CreateInDto createInDto) {
        //将生产订单行执行至开工
        try {
            //修改替代料比例
//            ppBomChange(moBill, createInDto);
//            sqlTool.excuteStartWork(moBill.getId(), FormIdEnum.proMo, "ToStart");
        }catch (Exception e){
            deleteTargetBill(moBill.getId());
            throw new ProcedureException("生产订单行执行至开工失败");
        }
//        //下推生产领料
//        String pickMtlId = moToMtrl(moBill, createInDto);
//        //下推生产入库
//        String moToMoInStock = moToMoInStock(moBill, createInDto, pickMtlId);
    }

    //用料清单变更
    public void ppBomChange(RequestResult moBill, CreateInDto createInDto){
        if (createInDto.getReserved5() != null){
            String planId = String.valueOf(createInDto.getReserved5());
            //查询生产用料清单编号
            Map<String, Object> ppBomNumber = tBxStMapper.selectPpBomNumber(moBill.getNumber());
            //查询替代件
            List<Map<String, Object>> insertList = tBxStMapper.getInsertItem(ppBomNumber.get("billNo").toString(), planId);
            //修改用料清单中的替代件比例
            try {
                ppBom.updateTargetBillEntryList(ppBomNumber.get("billId").toString(), insertList);
            }catch (Exception e){
                //删除生产订单
                deleteTargetBill(moBill.getId());
                throw  new ProcedureException(e.getMessage());
            }
        }
    }

    //生产订单下推生产入库
    public String moToMoInStock(RequestResult moBill, CreateInDto createInDto, String pickMtlId){
        //生产用料清单下推生产领料
        List<String> numbers = new ArrayList<>();
        numbers.add(moBill.getNumber());
        PushDto pushDto = new PushDto();
        pushDto.setSrcFormId(FormIdEnum.proMo);
        pushDto.setTargetFormId(FormIdEnum.proInStock);
        pushDto.setEnableDefaultRule(true);
        pushDto.setNumbers(numbers);
        FolderKingdee folderKingdee = new FolderKingdee(proInStock);
        try {
            RequestResult requestResult = folderKingdee.pushDown(pushDto);
            String moInStockId = "";
            try {
                //查询生产入库单明细行id
                QueryObject inventorySelect = new QueryObject(FormIdEnum.proInStock);
                ArrayList<String> resultKeyArray = new ArrayList<>();
                inventorySelect.addSelect("FEntity_FEntryID");//明细行id
                resultKeyArray.add("entryId");
                inventorySelect.addSelect("FSrcEntryId");//来源单据分录内码
                resultKeyArray.add("srcEntryId");
                inventorySelect.addCondition("fid", requestResult.getId());
                ArrayList<HashMap<String, Object>> targetEntryInfo = sqlTool.weaveResult(inventorySelect, resultKeyArray);
                //构建收料通知单明细行id和原单行id对应关系
                Map<String, String> keyValue = new HashMap<>();
                for (HashMap<String, Object> sld : targetEntryInfo) {
                    keyValue.put(sld.get("entryId").toString(), sld.get("srcEntryId").toString());
                }
                //修改目标单据信息
                RequestResult result = proInStock.updateTargetBillEntry(requestResult.getId(), keyValue, createInDto);
                if (result.get("code").equals("500")){
                    throw new ProcedureException(result.getMsg());
                }else {
                    moInStockId = result.getNumber();
                }
            }catch (ProcedureException e){
                //删除入库单
                proInStock.deleteTargetBill(requestResult.getId());
                //反审核领料单
                pickMtl.unAuditDataObject(pickMtlId);
                //删除领料单
                pickMtl.deleteTargetBill(pickMtlId);
                throw new ProcedureException(e.getMsg());
            }

            try {
                //审核入库单
                folderKingdee.auditTargetBill(moInStockId);
            }catch (ProcedureException e){
                //反审核入库
                proInStock.unAuditDataObject(requestResult.getId());
                //删除入库单
                proInStock.deleteTargetBill(requestResult.getId());
                //反审核领料单
                pickMtl.unAuditDataObject(pickMtlId);
                //删除领料单
                pickMtl.deleteTargetBill(pickMtlId);
                throw new ProcedureException(e.getMsg());
            }
            return requestResult.getId();
        }catch (Exception e){
            //反执行生产订单至计划确认
            sqlTool.excuteStartWork(moBill.getId(), FormIdEnum.proMo, "UndoToPlanConfirm");
            //删除生产订单
            deleteTargetBill(moBill.getId());
            throw  new ProcedureException(e.getMessage());
        }
    }

    //生产订单下推生产领料
    public String moToMtrl(RequestResult moBill, CreateInDto createInDto){
        //查询生产用料清单编号
        Map<String, Object> ppBomNumber = tBxStMapper.selectPpBomNumber(moBill.getNumber());
        //生产用料清单下推生产领料
        List<String> numbers = new ArrayList<>();
        numbers.add(ppBomNumber.get("billNo").toString());
        PushDto pushDto = new PushDto();
        pushDto.setSrcFormId(FormIdEnum.prdPpBom);
        pushDto.setTargetFormId(FormIdEnum.prdPickMtrl);
        pushDto.setEnableDefaultRule(false);
        pushDto.setRuleId("PRD_PPBOM2PICKMTRL_NORMAL");
        pushDto.setNumbers(numbers);
        FolderKingdee folderKingdee = new FolderKingdee(pickMtl);
        try {
            RequestResult requestResult = folderKingdee.pushDown(pushDto);
            String mtrlId = "";
            try {
                //查询目标单据信息
                QueryObject inventorySelect = new QueryObject(FormIdEnum.prdPickMtrl);
                ArrayList<String> resultKeyArray = new ArrayList<>();
                inventorySelect.addSelect("FEntity_FEntryID");//明细行id
                resultKeyArray.add("entryId");
                inventorySelect.addSelect("FEntrySrcEnteryId");//原单分录内码
                resultKeyArray.add("srcEntryId");
                inventorySelect.addCondition("fid", requestResult.getId());
                ArrayList<HashMap<String, Object>> targetEntryInfo = sqlTool.weaveResult(inventorySelect, resultKeyArray);
                //构建收料通知单明细行id和原单行id对应关系
                Map<String, String> keyValue = new HashMap<>();
                for (HashMap<String, Object> sld : targetEntryInfo) {
                    keyValue.put(sld.get("entryId").toString(), sld.get("srcEntryId").toString());
                }
                //修改目标单据信息
                RequestResult result = pickMtl.updateTargetBillEntry(requestResult.getId(), keyValue, createInDto);
                if (result.get("code").equals("500")){
                    throw new ProcedureException(result.getMsg());
                }else {
                    mtrlId = result.getNumber();
                }
            }catch (ProcedureException e){
                //删除领料单
                folderKingdee.deleteTargetBill(String.valueOf(requestResult.getId()));
                throw new ProcedureException(e.getMsg());
            }

            try {
                //审核领料单
                folderKingdee.auditTargetBill(mtrlId);
            }catch (ProcedureException e){
                //反审核领料单
                pickMtl.unAuditDataObject(requestResult.getId());
                //删除领料单
                folderKingdee.deleteTargetBill(String.valueOf(requestResult.getId()));
                throw new ProcedureException(e.getMsg());
            }
            return requestResult.getId();
        }catch (Exception e){
            //反执行生产订单至计划确认
            sqlTool.excuteStartWork(moBill.getId(), FormIdEnum.proMo, "UndoToPlanConfirm");
            //删除生产订单
            deleteTargetBill(moBill.getId());
            throw  new ProcedureException(e.getMessage());
        }
    }

    @Override
    public void deleteTargetBill(String fid) {
        //反审核生产订单
        DataObject unAuditDataObject = new DataObject(FormIdEnum.proMo);
        unAuditDataObject.addIds(fid);
        sqlTool.unAuditBatchData(unAuditDataObject);
        //删除生产订单
        sqlTool.deleteBill(fid, FormIdEnum.proMo);
    }
}
